package communication;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.Vector;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

import clientCommunicationHandler.UserInfo;
import clientCommunicationHandler.UserInterfaceMsgHandler;
import clientCommunicationHandler.sync;

public class TelnetClient implements Runnable{

	public static StringBuilder menu = new StringBuilder("[user: "+UserInfo.userName+"] please make your choice:\n\t1. Login\n\t2. Register\n\t3. view_Forums\n\t4. Exit");
	public static StringBuilder welcom_page = new StringBuilder("please make your choice:\n\t1. Login\n\t2. Register\n\t3. view_Forums\n\t4. Exit");
	public static BufferedReader in;
	public static ClientBootstrap bootstrap;
	public static ChannelFuture lastWriteFuture;
	public static Channel channel;

	public TelnetClient(String serverIp,int comunicationPort) throws Throwable{
		String host = serverIp;
		int port = comunicationPort;

		//Configure the client
		ClientBootstrap bootstrap = new ClientBootstrap
				(new NioClientSocketChannelFactory
						(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

		//configure the pipe line factory
		bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());

		//start the connection attempt
		ChannelFuture future = bootstrap.connect(new InetSocketAddress(host,port));

		//wait until the connection attempt succeeds or fails.
		channel = future.awaitUninterruptibly().getChannel();
		if(!future.isSuccess()){
//			throw future.getCause();
			future.getCause().printStackTrace();
			bootstrap.releaseExternalResources();
			return;
		}

		lastWriteFuture = null;
		TelnetClient.in = new BufferedReader(new InputStreamReader(System.in));
	}

	public static void sendMessageToServer(String message){
//		System.out.println("sending: "+message);
		lastWriteFuture = channel.write(message+"\n\0\n");
		boolean wantToExit = checkIfExitMsg(message);
		if (wantToExit){
			channel.getCloseFuture().awaitUninterruptibly();
			closeConnection();
			System.exit(0);
		}


	}
	private static boolean checkIfExitMsg(String message) {
		int delimiterIndex = message.indexOf((char)1+"");
		String messageHeader =(delimiterIndex > 0 ? message.substring(0,delimiterIndex) : message);
		boolean exit = messageHeader.equalsIgnoreCase("bye"); 
		return exit;
	}

	private static void closeConnection(){
		//wait until all messages are flushed before closing the channel.


		{
			lastWriteFuture.awaitUninterruptibly();
		}


		//close the connection. Make sure the close operation ends
		//because all I/O operation are asynchronous in Netty
		channel.close().awaitUninterruptibly();

		//Shut down all thread pools to exit.
		bootstrap.releaseExternalResources();

	}

	@Override
	public void run() {
		System.out.println("welcom to our Forum.");
		
		UserInterfaceMsgHandler userMsgHandler = new UserInterfaceMsgHandler();
		String line;
		//listen to user
		for(;;){
			sync.isReady = false;
			line = null;
			System.out.println(menu);
			String [] tMenuInArray = menu.toString().split("\t");
			int tUserRequest = 0;
			while(line == null){
				try{
					line = in.readLine();
						if(line.equalsIgnoreCase("exit"))
							sendMessageToServer("bye");
					tUserRequest = Integer.parseInt(line);
					if(!(tUserRequest>0 && tUserRequest < tMenuInArray.length)){
						line = null;
						System.out.println("please enter number from 1 to "+tMenuInArray.length);
					}
				}
				catch(Exception e){
					line = null;
					System.out.println("invalid input please enter a number");
				}
			}
			line = userMsgHandler.parserUserChooice(tUserRequest,tMenuInArray);//take care of the user requests.parse the menu choice into legal protocol.

			if(line == null){
				break;
			}

//			System.out.println("going to send to server: "+line+"*");
			sendMessageToServer(line);
			synchronized (sync.class) {
//				System.out.println("flag = " +sync.isReady);
				if(sync.isReady == false)
					try {
						sync.class.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			}
		}
		


	}
}
